package org.testis.orm.refinedclasses;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import org.orm.PersistentException;
import org.testis.orm.classes.T_bed_dut;
import org.testis.orm.classes.T_bed_networkadapters;
import org.testis.orm.classes.T_bed_testpc;
import org.testis.orm.classes.T_test_designtree;
import org.testis.orm.classes.T_test_designtreeCriteria;
import org.testis.orm.classes.T_test_label;
import org.testis.orm.classes.T_test_labelpairs;
import org.testis.orm.classes.T_test_teststeps;
import org.testis.orm.refinedclasses.TestDesignTreeRefined.TestDesignTreeParameters;
import org.testis.utils.middleware.LabelDataHandler;
import org.testis.utils.middleware.LabelUtils;
import org.testis.utils.middleware.TestDesign;

/**
 * 
 * @author Cahit Emir Erel
 */
public class TestStepRefined extends DesignPart implements ILabelContainer {

    private T_test_teststeps m_reference;

    public TestStepRefined(T_test_teststeps reference) {
	setReference(reference);
    }

    synchronized public TestStepRefined createRefinedDatabaseCopy()
	    throws PersistentException {
	// return new TestStepRefined(getReference());
	return new TestStepRefined(createDatabaseCopy());
    }

    private T_test_teststeps createDatabaseCopy() throws PersistentException {
	T_test_teststeps newStep = new T_test_teststeps();
	newStep.setDescription(getReference().getDescription());
	newStep.setName(getReference().getName());
	newStep.setModulTypeId(getReference().getModulTypeId());
	newStep.setActionId(getReference().getActionId());
	newStep.setSupportedDeviceGroupId(getReference()
		.getSupportedDeviceGroupId());

	if (newStep.save()) {

	    return newStep;
	} else {
	    throw new PersistentException(
		    "Unable to create database copy of Data Object: " + this);
	}
    }

    public boolean isPreset() {
	try {
	    T_test_designtreeCriteria t_test_designtreeCriteria = new T_test_designtreeCriteria();
	    t_test_designtreeCriteria.elementId.eq(getId());
	    t_test_designtreeCriteria.typeId.eq(TestDesign
		    .getDesignPartTypeIdByName("TestStep"));
	    T_test_designtree[] list = t_test_designtreeCriteria
		    .listT_test_designtree();
	    if (list != null && list.length > 1) {
		return true;
	    }
	} catch (PersistentException ex) {
	    ex.printStackTrace();
	}
	return false;
    }

    @Override
    public boolean delete() {
	TestDesign.newInstance().removeTestSuite(this.getName());
	boolean result = false;
	try {
	    T_test_designtreeCriteria t_test_designtreeCriteria = new T_test_designtreeCriteria();
	    t_test_designtreeCriteria.elementId.eq(this.getId());
	    t_test_designtreeCriteria.typeId.eq(TestDesign
		    .getDesignPartTypeIdByName("TestStep"));
	    T_test_designtree[] theOthers = t_test_designtreeCriteria
		    .listT_test_designtree();
	    int length = theOthers.length;
	    if (length > 1) {
		result = true;
	    } else {
		if (getReference().deleteAndDissociate()) {
		    result = true;
		} else {
		    throw new PersistentException("Unable to delete Test Step");
		}
	    }
	} catch (PersistentException ex) {
	    ex.printStackTrace();
	}
	return result;
    }

    public String toString(TestDesignTreeNode treeNode) {
	try {
	    StringBuffer buffer = new StringBuffer();
	    buffer.append(this.toString());
	    buffer.append("\nCritical: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.Critical.name()));
	    buffer.append("\nRun Always: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.RunAlways.name()));
	    buffer.append("\nThread Pool Size: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.ThreadPoolSize.name()));
	    buffer.append("\nInvocation Count: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.InvocationCount.name()));
	    buffer.append("\nSuccess Percentage: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.SuccessPercentage.name()));
	    buffer.append("\nTimeout: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.Timeout.name()));
	    buffer.append("\nNumber of Retry of Fail: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.NoOfRetryOnFail.name()));

	    buffer.append("\nData Array Applies to Case: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.DataArrayAppliestoCase
				    .name()));
	    buffer.append("\nDelay Time: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.DelayTime.name()));
	    buffer.append("\nASynch Call: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.AsynchCall.name()));

	    buffer.append("\n\nBrowser Speed: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.BrowserSpeed.name()));
	    buffer.append("\nBrowser Type: "
		    + treeNode.getReference().getParameterStringValue(
			    TestDesignTreeParameters.BrowserType.name()));

	    Integer pcId = treeNode.getReference().getParameterIntValue(
		    TestDesignTreeParameters.PcId.name());
	    Integer deviceId = treeNode.getReference().getParameterIntValue(
		    TestDesignTreeParameters.DeviceId.name());
	    Integer nicId = treeNode.getReference().getParameterIntValue(
		    TestDesignTreeParameters.NicId.name());
	    String deviceIp = treeNode.getReference().getParameterStringValue(
		    TestDesignTreeParameters.DeviceIp.name());
	    if (pcId != null) {
		buffer.append("\n\nConnected to\nPc Name: "
			+ TestDesign.getPcById(pcId).getName());
	    }
	    if (deviceId != null) {
		T_bed_dut dut = TestDesign.getDutById(deviceId);
		buffer.append("\n\nDevice Id: " + dut.getId());
		buffer.append("\nDevice Unique Name: " + dut.getName());
		buffer.append("\nDevice Test Bed Ip: " + dut.getTestBedIp());
		buffer.append("\nDevice Active Firmware: "
			+ dut.getActiveFirmware().getName());
	    } else if (nicId != null) {
		buffer.append("\n\nNic Id: "
			+ TestDesign.getNicById(nicId).getName());
	    }
	    if (deviceIp != null) {
		buffer.append("\n\nDevice IP: " + deviceIp);
	    }
	    buffer.append("\n\n\nLabels: ");
	    T_test_label[] labels = getLabelsAsArray();
	    if (labels != null && labels.length > 0) {
		for (int i = 0; i < labels.length; i++) {
		    buffer.append("\n\t" + labels[i].getName());
		}
	    } else {
		buffer.append("\tNo labels found");
	    }

	    return buffer.toString();
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}

    }

    @Override
    public String toString() {
	try {
	    StringBuffer buffer = new StringBuffer();
	    buffer.append("Type: TestStep");
	    buffer.append("\nName: " + this.getName());
	    buffer.append("\nTest Step Id:" + this.getId());
	    buffer.append("\nDescription: "
		    + this.getReference().getDescription());

	    buffer.append("\nAction: "
		    + TestDesign.getActionTypeName(this.getReference()
			    .getActionId()));
	    buffer.append("\nModule Type: "
		    + TestDesign.getModuleTypeName(this.getReference()
			    .getModulTypeId()));
	    return buffer.toString();
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    public T_test_teststeps getReference() {
	return m_reference;
    }

    private void setReference(Identifier reference) {
	if (reference == null) {
	    throw new NullPointerException();
	}
	if (reference instanceof T_test_teststeps) {
	    m_reference = (T_test_teststeps) reference;
	}
    }

    public String getTypeName() {
	return "TestStep";
    }

    public int compare(Comparable source) {
	TestStepRefined sourceDataObject = (TestStepRefined) source;
	if (sourceDataObject.getReference().getModulTypeId() == getReference()
		.getModulTypeId()
		|| sourceDataObject.getReference().getActionId() == getReference()
			.getActionId()
		|| sourceDataObject.getReference().getSupportedDeviceGroupId() != getReference()
			.getSupportedDeviceGroupId()) {
	    return Comparable.DIFFERENT_PROPERTIES;
	}
	return Comparable.EXACT;
    }

    public int compare(Comparable source, Comparable treeReference) {
	TestDesignTreeNode src = (TestDesignTreeNode) source;
	TestDesignTreeNode dest = (TestDesignTreeNode) treeReference;
	String srcBrowserSpeed = src.getReference().getParameterValue(
		TestDesignTreeParameters.BrowserSpeed.name());
	String srcBrowserType = src.getReference().getParameterValue(
		TestDesignTreeParameters.BrowserType.name());
	String srcPc = src.getReference().getParameterValue(
		TestDesignTreeParameters.PcId.name());
	String srcDevice = src.getReference().getParameterValue(
		TestDesignTreeParameters.DeviceId.name());
	String srcDeviceIp = src.getReference().getParameterValue(
		TestDesignTreeParameters.DeviceIp.name());
	String srcNic = src.getReference().getParameterValue(
		TestDesignTreeParameters.NicId.name());
	String srcSuccessPercentage = src.getReference().getParameterValue(
		TestDesignTreeParameters.SuccessPercentage.name());
	String srcDelayTime = src.getReference().getParameterValue(
		TestDesignTreeParameters.DelayTime.name());
	String srcDataArrayAppliestoCase = src.getReference()
		.getParameterValue(
			TestDesignTreeParameters.DataArrayAppliestoCase.name());
	String srcAsynchCall = src.getReference().getParameterValue(
		TestDesignTreeParameters.AsynchCall.name());
	String srcNoOfRetryOnFail = src.getReference().getParameterValue(
		TestDesignTreeParameters.NoOfRetryOnFail.name());
	String srcCritical = src.getReference().getParameterValue(
		TestDesignTreeParameters.Critical.name());
	String srcTimeout = src.getReference().getParameterValue(
		TestDesignTreeParameters.Timeout.name());

	String destBrowserSpeed = dest.getReference().getParameterValue(
		TestDesignTreeParameters.BrowserSpeed.name());
	String destBrowserType = dest.getReference().getParameterValue(
		TestDesignTreeParameters.BrowserType.name());
	String destPc = dest.getReference().getParameterValue(
		TestDesignTreeParameters.PcId.name());
	String destDevice = dest.getReference().getParameterValue(
		TestDesignTreeParameters.DeviceId.name());
	String destDeviceIp = dest.getReference().getParameterValue(
		TestDesignTreeParameters.DeviceIp.name());
	String destNic = src.getReference().getParameterValue(
		TestDesignTreeParameters.NicId.name());
	String destSuccessPercentage = src.getReference().getParameterValue(
		TestDesignTreeParameters.SuccessPercentage.name());
	String destDelayTime = src.getReference().getParameterValue(
		TestDesignTreeParameters.DelayTime.name());
	String destDataArrayAppliestoCase = dest.getReference()
		.getParameterValue(
			TestDesignTreeParameters.DataArrayAppliestoCase.name());
	String destAsynchCall = dest.getReference().getParameterValue(
		TestDesignTreeParameters.AsynchCall.name());
	String destNoOfRetryOnFail = src.getReference().getParameterValue(
		TestDesignTreeParameters.NoOfRetryOnFail.name());
	String destCritical = src.getReference().getParameterValue(
		TestDesignTreeParameters.Critical.name());
	String destTimeout = src.getReference().getParameterValue(
		TestDesignTreeParameters.Timeout.name());

	if ((srcBrowserSpeed == null ? destBrowserSpeed != null
		: !srcBrowserSpeed.equals(destBrowserSpeed))
		|| (srcBrowserType == null ? destBrowserType != null
			: !srcBrowserType.equals(destBrowserType))
		|| (srcPc == null ? destPc != null : !srcPc.equals(destPc))
		|| (srcDevice == null ? destDevice != null : !srcDevice
			.equals(destDevice))
		|| (srcDeviceIp == null ? destDeviceIp != null : !srcDeviceIp
			.equals(destDeviceIp))
		|| (srcNic == null ? destNic != null : !srcNic.equals(destNic))
		|| (srcSuccessPercentage == null ? destSuccessPercentage != null
			: !srcSuccessPercentage.equals(destSuccessPercentage))
		|| (srcDelayTime == null ? destDelayTime != null
			: !srcDelayTime.equals(destDelayTime))
		|| (srcDataArrayAppliestoCase == null ? destDataArrayAppliestoCase != null
			: !srcDataArrayAppliestoCase
				.equals(destDataArrayAppliestoCase))
		|| (srcDelayTime == null ? destDelayTime != null
			: !srcDelayTime.equals(destDelayTime))
		|| (srcAsynchCall == null ? destAsynchCall != null
			: !srcAsynchCall.equals(destAsynchCall))
		|| (srcNoOfRetryOnFail == null ? destNoOfRetryOnFail != null
			: !srcNoOfRetryOnFail.equals(destNoOfRetryOnFail))
		|| (srcTimeout == null ? destTimeout != null : !srcTimeout
			.equals(destTimeout))
		|| (srcCritical == null ? destCritical != null : !srcCritical
			.equals(destCritical))) {
	    return Comparable.DIFFERENT_PROPERTIES;

	}
	return compare(src.getObject());

    }

    private boolean hasSameStaticParameters(HashMap<String, Object> params,
	    Comparable treeReference) {
	String action = (String) params.get("action");
	String modulType = (String) params.get("modulType");
	String description = (String) params.get("description");
	String aSynchCall = (String) params.get("aSynchCall");
	String critical = (String) params.get("critical");
	String dataArrayAppliesToCase = (String) params
		.get("dataArrayAppliesToCase");
	String delayTime = (String) params.get("delayTime");
	String noOfRetryOnFail = (String) params.get("noOfRetryOnFail");
	String successPercentage = (String) params.get("successPercentage");
	String supportedDeviceGroup = (String) params
		.get("supportedDeviceGroup");
	String timeout = (String) params.get("timeout");
	LinkedList<String> labels = (LinkedList<String>) params.get("labels");

	TestDesignTreeNode testDesignTreeNode = (TestDesignTreeNode) treeReference;
	TestStepRefined tsRefined = (TestStepRefined) ((TestDesignTreeNode) testDesignTreeNode)
		.getObject();

	String curmoduleTypeName = TestDesign.getModuleTypeName(tsRefined
		.getReference().getModulTypeId());
	String curactiontypeName = TestDesign.getActionTypeName(tsRefined
		.getReference().getActionId());
	String cursupportedDeviceGroupTypeName = TestDesign
		.getSupportedDeviceGroupName(tsRefined.getReference()
			.getSupportedDeviceGroupId());
	if (modulType != null) {
	    if (modulType == null ? curmoduleTypeName != null : !modulType
		    .equals(curmoduleTypeName)) {
		return false;
	    }
	}
	if (action != null) {
	    if (action == null ? curactiontypeName != null : !action
		    .equals(curactiontypeName)) {
		return false;
	    }
	}
	if (cursupportedDeviceGroupTypeName == null ? supportedDeviceGroup != null
		: !cursupportedDeviceGroupTypeName.equals(supportedDeviceGroup)) {
	    return false;
	}
	if (tsRefined != null) {
	    HashMap myLabels = tsRefined.getLabelsAsHashMap();
	    if (myLabels.size() != labels.size()) {
		return false;
	    }
	    Iterator iterator = myLabels.keySet().iterator();
	    while (iterator.hasNext()) {
		T_test_label myLabel = (T_test_label) myLabels.get(iterator
			.next());
		if (!labels.contains(myLabel.getName())) {
		    return false;
		}
	    }
	}
	String curCritical = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.Critical.name());
	String curAsync = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.AsynchCall.name());
	String curDataArray = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.DataArrayAppliestoCase.name());
	String curSucPer = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.SuccessPercentage.name());
	String curRetry = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.NoOfRetryOnFail.name());
	String curDelay = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.DelayTime.name());
	String curTimeout = testDesignTreeNode.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.Timeout.name());

	if ((curCritical == null ? critical == null : curCritical
		.equals(critical))
		&& (curDataArray == null ? dataArrayAppliesToCase == null
			: curDataArray.equals(dataArrayAppliesToCase))
		&& (curDelay == null ? delayTime == null : curDelay
			.equals(delayTime))
		&& (curRetry == null ? noOfRetryOnFail == null : curRetry
			.equals(noOfRetryOnFail))
		&& (curSucPer == null ? successPercentage == null : curSucPer
			.equals(successPercentage))
		&& (curTimeout == null ? timeout == null : curTimeout
			.equals(timeout))
		&& (curAsync == null ? aSynchCall == null : curAsync
			.equals(aSynchCall))
		&& getReference().getDescription().equals(description)) {
	    return true;

	} else {

	    return false;

	}
    }

    public boolean compareParameters(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return hasSameStaticParameters(params, treeTreference);

    }

    public boolean hasSameRunTimeParams(HashMap<String, Object> params,
	    Comparable reference) {
	String browserSpeed = (String) params.get("browserSpeed");
	String browserType = (String) params.get("browserType");
	String pc = (String) params.get("pc");
	String dut = (String) params.get("dut");
	String nic = (String) params.get("nic");
	String deviceIp = (String) params.get("deviceIp");

	if (deviceIp == null) {
	    deviceIp = "";

	}
	if (pc == null) {
	    pc = "";

	}
	if (dut == null) {
	    dut = "";

	}
	if (nic == null) {
	    nic = "";

	}
	TestDesignTreeNode treeTreference = (TestDesignTreeNode) reference;

	String currentBrowserSpeed = treeTreference.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.BrowserSpeed.name());
	String currentBrowserType = treeTreference.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.BrowserType.name());
	String currentPc = "";
	String currentDut = "";
	String currentNic = "";
	String currentDeviceIp = treeTreference.getReference()
		.getParameterStringValue(
			TestDesignTreeParameters.DeviceIp.name());

	if (currentBrowserSpeed == null) {
	    currentBrowserSpeed = "600";

	}

	if (!currentBrowserSpeed.equals(browserSpeed)) {
	    return false;

	}
	if (currentBrowserType == null) {
	    currentBrowserType = "";

	}
	if (!currentBrowserType.equals(browserType) && !browserType.equals("*")) {
	    return false;

	}
	Integer pcId = treeTreference.getReference().getParameterIntValue(
		TestDesignTreeParameters.PcId.name());

	if (pcId != null) {
	    T_bed_testpc pcData = TestDesign.getPcById(pcId);

	    if (pcData != null) {
		currentPc = TestDesign.getPcById(pcId).getName();

	    }

	}
	if (!currentPc.equals(pc)) {
	    return false;

	}
	Integer deviceId = treeTreference.getReference().getParameterIntValue(
		TestDesignTreeParameters.DeviceId.name());

	if (deviceId != null) {
	    T_bed_dut dutData = TestDesign.getDutById(deviceId);

	    if (dutData != null) {
		currentDut = dutData.getName();

	    }

	}
	if (!currentDut.equals(dut)) {
	    return false;

	}
	Integer nicId = treeTreference.getReference().getParameterIntValue(
		TestDesignTreeParameters.NicId.name());

	if (nicId != null) {
	    T_bed_networkadapters adapterData = TestDesign.getNicById(nicId);

	    if (adapterData != null) {
		currentNic = adapterData.getName();

	    }

	}
	if (!currentNic.equals(nic)) {
	    return false;

	}

	if (currentDeviceIp == null) {
	    currentDeviceIp = "";

	}
	if (!currentDeviceIp.equals(deviceIp)) {
	    return false;

	}
	return true;

    }

    public T_test_label[] getLabelsAsArray() {
	T_test_label[] labels = null;

	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    T_test_labelpairs[] labelpairs = getReference().t_test_labelpairs
		    .toArray();
	    labels = new T_test_label[labelpairs.length];
	    for (int i = 0; i < labelpairs.length; i++) {
		labels[i] = handler.getLabelById(labelpairs[i].getLabelId());
	    }
	}
	return labels;
    }

    public HashMap getLabelsAsHashMap() {
	HashMap result = new HashMap();
	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    T_test_labelpairs[] labelpairs = getReference().t_test_labelpairs
		    .toArray();
	    for (int i = 0; i < labelpairs.length; i++) {
		T_test_label label = handler.getLabelById(labelpairs[i]
			.getLabelId());
		result.put(label.getId(), label);
	    }
	}
	return result;
    }

    public String getLabelsAsString(boolean inheritance) {
	return LabelUtils
		.convertLabelsToString(getLabelsAsArray(), inheritance);

    }

    public boolean matchesLabelPattern(String regex) {
	return LabelUtils.matchesLabelPattern(regex, getLabelsAsString(true));

    }
}
